import Vec4 from '@pages/cube/Vec4';
type MatValue = [Vec4, Vec4, Vec4, Vec4];
export default class Mat4 {
  public values: [
    [number, number, number, number],
    [number, number, number, number],
    [number, number, number, number],
    [number, number, number, number]
  ];
  constructor(public value: MatValue) {
    this.values = [
      [value[0].x, value[0].y, value[0].z, value[0].w],
      [value[1].x, value[1].y, value[1].z, value[1].w],
      [value[2].x, value[2].y, value[2].z, value[2].w],
      [value[3].x, value[3].y, value[3].z, value[3].w],
    ];
    // nothing
  }
  xRotation(angle: number) {
    var c = Math.cos(angle);
    var s = Math.sin(angle);
    return this.multiply(
      new Mat4([
        new Vec4(1, 0, 0, 0),
        new Vec4(0, c, s, 0),
        new Vec4(0, -s, c, 0),
        new Vec4(0, 0, 0, 1),
      ])
    );
  }
  yRotation(angle: number) {
    var c = Math.cos(angle);
    var s = Math.sin(angle);
    return this.multiply(
      new Mat4([
        new Vec4(c, 0, -s, 0),
        new Vec4(0, 1, 0, 0),
        new Vec4(s, 0, c, 0),
        new Vec4(0, 0, 0, 1),
      ])
    );
  }
  zRotation(angle: number) {
    var c = Math.cos(angle);
    var s = Math.sin(angle);
    return this.multiply(
      new Mat4([
        new Vec4(c, s, 0, 0),
        new Vec4(-s, c, 0, 0),
        new Vec4(0, 0, 1, 0),
        new Vec4(0, 0, 0, 1),
      ])
    );
  }
  translate(t: Vec4): Mat4 {
    return this.multiply(
      new Mat4([
        new Vec4(1, 0, 0, t.x),
        new Vec4(0, 1, 0, t.y),
        new Vec4(0, 0, 1, t.z),
        new Vec4(0, 0, 0, 1),
      ])
    );
  }
  scale(s: Vec4): Mat4 {
    return this.multiply(
      new Mat4([
        new Vec4(s.x, 0, 0, 0),
        new Vec4(0, s.y, 0, 0),
        new Vec4(0, 0, s.z, 0),
        new Vec4(0, 0, 0, 1),
      ])
    );
  }
  multiply(mat: Mat4): Mat4 {
    const m1 = this.value;
    const m2 = mat.value;
    // console.log('m1', m1);
    // console.log('m2', m2);
    const m: MatValue = [
      new Vec4(0, 0, 0, 0),
      new Vec4(0, 0, 0, 0),
      new Vec4(0, 0, 0, 0),
      new Vec4(0, 0, 0, 0),
    ];
    for (let i = 0; i < 4; i++) {
      for (let j = 0; j < 4; j++) {
        const v =
          m1[i].x * m2[0].getByIndex(j) +
          m1[i].y * m2[1].getByIndex(j) +
          m1[i].z * m2[2].getByIndex(j) +
          m1[i].w * m2[3].getByIndex(j);
        // console.log(i, j, v);
        m[i].setByIndex(j, v);
      }
    }
    return new Mat4(m);
  }
  multiplyVec(vec: Vec4): Vec4 {
    const m = this.value;
    return new Vec4(
      vec.x * m[0].x + vec.y * m[0].y + vec.z * m[0].z + vec.w * m[0].w,
      vec.x * m[1].x + vec.y * m[1].y + vec.z * m[1].z + vec.w * m[1].w,
      vec.x * m[2].x + vec.y * m[2].y + vec.z * m[2].z + vec.w * m[2].w,
      vec.x * m[3].x + vec.y * m[3].y + vec.z * m[3].z + vec.w * m[3].w
    );
  }
}
